package org.vectrics.user.web.struts;


import java.util.Collection;
import java.util.Iterator;
import java.util.TreeSet;

import org.vectrics.SystemException;
import org.vectrics.common.html.BorderTable;
import org.vectrics.common.html.Table;
import org.vectrics.common.html.Row;
import org.vectrics.common.html.Cell;
import org.vectrics.common.html.TextHelper;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.apache.ecs.html.Input;
import org.apache.log4j.Category;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.struts.VectricsTagSupport;
import org.vectrics.user.Person;
import org.vectrics.user.UserPrivilege;
import org.vectrics.user.UserPrivilegeType;
import org.vectrics.user.UserPrivilegeTypeNameComparator;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;


/**
 *@author     mmoore
 *@created    Sept 24, 2005
 */
public abstract class UserPrivilegesSelectTag extends VectricsTagSupport {
    private static Category log = Category.getInstance(UserPrivilegesSelectTag.class);
    public static String CANDIDATE_PARAM = "candidate";
	private String contextPath = null;
	private String personId = null;
	private String domainId = null;
	private String hidden = null;
	private String global = "false";
	private UserPrivilegesHelper userPrivilegeHelper = new UserPrivilegesHelper();

    public UserPrivilegesSelectTag() { }
	protected abstract Collection getRoles();

	protected String getContextPath() {
		return(contextPath);
	}
	
	/**
	 * @return Returns the global.
	 */
	public String getGlobal() {
		return global;
	}
	/**
	 * @param global The global to set.
	 */
	public void setGlobal(String global) {
		this.global = global;
	}

	public boolean getGlobalBoolean() {
		return(this.global.equals("true"));
	}
	
	public String makeStartTag() {
        log.info("makeStartTag() called");
		StringBuffer html = new StringBuffer();
		try {
			ServletRequest request = super.pageContext.getRequest();
			HttpServletRequest httpRequest = (HttpServletRequest)request;
			contextPath = httpRequest.getContextPath();
			
			log.debug("doStartTag() - finding person = " + getPersonId());
			Person person = null;		
			if (getPersonId() != null)
				person = CoreServiceLocator.getPersonService().findPersonById(new Long(getPersonId()));
	
			if (person == null) {
				log.debug("UserPrivilegesSelectTag - Could not find person: " + getPersonId());
			}
			
			if (this.getGlobalBoolean()) {
				if (this.getHiddenBoolean()) {
					log.debug("Global and hidden");
					html.append(makeHiddenInputs(person, getRoles()));
				} else {
					html.append(makeRoleSection(person, getRoles()));
				}
			}
		}
		catch (Exception ex) {
			log.error("doStartTag() - exception ", ex);
			throw new SystemException("doStartTag() - exception ", ex);
		}
		return(html.toString());
    }

	private String makeHiddenInputs(Person person, Collection roles) {
		Person authPerson = ThreadProperties.getPerson();
		StringBuffer html = new StringBuffer();
		Iterator iter = roles.iterator();
		while (iter.hasNext()) {
    		UserPrivilegeType roleType = (UserPrivilegeType)iter.next();
			if (CoreServiceLocator.getUserAuthService().hasRightToAssignPrivilege(authPerson, roleType)) {
				String paramName = userPrivilegeHelper.getHiddenParameterName(roleType);
				html.append("<input type=\"hidden\" name=\"");
	    		html.append(paramName);
	    		html.append("\" value=\"entered");
	    		html.append("\">");
			}
		}
		return(html.toString());
	}

	private void makeHeaderRow(Table table) {
		Row row = table.addRow();
		Cell cell = row.addCell();
		cell.setColSpan(1);
		
		row.addCell().addText("stdBoldFont", this.getPhrase("prompt.person.roles.not.assigned"));
		row.addCell().addText("stdBoldFont", this.getPhrase("prompt.person.roles.domain.only"));
		row.addCell().addText("stdBoldFont", this.getPhrase("prompt.person.roles.global"));
		row.addCell().addText("stdBoldFont", this.getPhrase("prompt.person.privilege.description"));
	}
	
	
    private Table makeRoleSection(Person person, Collection roles) {
		Person authPerson = ThreadProperties.getPerson();
    	TreeSet<UserPrivilegeTypeNameComparator> sortedRoles = new TreeSet<UserPrivilegeTypeNameComparator>(new UserPrivilegeTypeNameComparator());
    	sortedRoles.addAll(roles);
		Table table = new BorderTable();
    	table.setWidth(600);
    	Iterator iter = sortedRoles.iterator();
    	if (iter.hasNext() == false) {
    		log.warn("No privileges found to display");
    	} else {
    		String prevGroupCode = "";
    		while (iter.hasNext()) {
	    		UserPrivilegeType roleType = (UserPrivilegeType)iter.next();
	    		log.info("Displaying selection control for roleType = " + roleType);
	    		if (false == roleType.getUserPrivilegeTypeGroup().getCode().equals(prevGroupCode)) {
	    			Row row = table.addRow();
	    			Cell cell = row.addCell();
	    			cell.setClass("formBg1");
	    			
	    			cell.addText("stdFont", "<br><b>" + this.getPhrase(roleType.getUserPrivilegeTypeGroup().getDescriptionCode())
	    					+ "</b>" 
//	    					+"<br>" + roleType.getCode()
	    					);
	    			cell.setColSpan(5);
	    			
	    			this.makeHeaderRow(table);
	    			prevGroupCode = roleType.getUserPrivilegeTypeGroup().getCode();
	    		}
	    		
   				UserPrivilege role = person.findPrivilege(roleType, this.getDomain());
   				boolean userHasRightToChangePrivilege = CoreServiceLocator.getUserAuthService().hasRightToAssignPrivilege(authPerson, roleType);
   				log.info("User has right to change privilege = " + userHasRightToChangePrivilege
   						+ "\r\n - authPerson = " + authPerson
   						+ "\r\n - roleType =   " + roleType);
	    		boolean personHasRolePriv = false;
   				boolean personHasGlobalPriv = false;
   				if (role != null) {
   					if (role.getGlobal()) {
   						personHasGlobalPriv = true;
   					} else {
   						personHasRolePriv = true;
   					}
   				}
	    		log.info("Creating checkbox for role: " + roleType.getCode() 
	    				+  " Person has role: " + personHasRolePriv 
	    				+ "  person.id=" + person.getId());
	    		Row row = table.addRow();
				//cell = row.addCell();
				//cell.addElement(TextHelper.getFont("subFont", this.getPhrase(roleType.getName())));
				
				Cell privLabelCell = row.addCell();
				privLabelCell.setVAlign("middle");
				privLabelCell.addElement(TextHelper.getFont("subFont", this.getPhrase(roleType.getName())));
				Cell noPrivCell = row.addCell();
				if (userHasRightToChangePrivilege) {
					Cell privCell = row.addCell();
					Cell privGlobalCell = row.addCell();
					String inputName = userPrivilegeHelper.getSelectParameterName(roleType);
					Input radioNo = new Input();
					radioNo.setType(Input.RADIO);
					radioNo.setChecked(false);
					radioNo.setName(inputName);
					radioNo.setValue("none");
					if ((personHasRolePriv == false) && (personHasGlobalPriv == false)) {
						radioNo.setChecked(true);
					}
					noPrivCell.addElement(radioNo);
	
					Input radioGroup = new Input();
					radioGroup.setType(Input.RADIO);
					radioGroup.setChecked(false);
					radioGroup.setName(inputName);
					radioGroup.setValue("domain");
					if (personHasRolePriv) {
						radioGroup.setChecked(true);
					}
					privCell.addElement(radioGroup);
					
	
				//	Allow any role to be global... for now.
					if (roleType.getGlobalRole()) {
						Input radioGlobalGroup = new Input();
						radioGlobalGroup.setType(Input.RADIO);
						radioGlobalGroup.setChecked(false);
						radioGlobalGroup.setName(inputName);
						radioGlobalGroup.setValue("global");
						if (personHasGlobalPriv) {
							radioGlobalGroup.setChecked(true);
						}
						privGlobalCell.addElement(radioGlobalGroup);
					} else {
						privGlobalCell.addElement("&nbsp;");
					}
				} else {
					noPrivCell.setColSpan(3);
				}
				Cell descriptionCell = row.addCell();
				descriptionCell.addText("stdFont", roleType.getDescription());

				if (userHasRightToChangePrivilege) {
				//	}
	
		    		//Row blankRow = table.addRow();
		    		//Cell blankCell = blankRow.addCell();
		    		//blankCell.setColSpan(5);
		    		//blankCell.addElement("&nbsp;");
				} else {
					if (personHasRolePriv) {
						noPrivCell.addElement(TextHelper.getFont("subFontGreen", this.getPhrase("phrase.has.role.privileges")));
					} else if (personHasGlobalPriv) {
						noPrivCell.addElement(TextHelper.getFont("subFontGreen", this.getPhrase("phrase.has.global.role.privileges")));
					} else {
						noPrivCell.addElement(TextHelper.getFont("subFontRed", this.getPhrase("phrase.has.not.role.privileges")));
					}
					if (userHasRightToChangePrivilege == false) {
						noPrivCell.addElement(TextHelper.getFont("subFont", "<br><i>Not authorized to change</i>"));
						
					}
				
				}
	    	}
    	}
    	return(table);
    }


    /**
	 * @return Returns the companyId.
	 */
	public String getDomainId() {
		return domainId;
	}
	/**
	 * @param companyId The companyId to set.
	 */
	public void setDomainId(String domainId) {
		this.domainId = domainId;
	}
	
	private Domain getDomain() {
		Domain domain = null;
		if ((this.getDomainId() != null) && (this.getDomainId().length() > 0)) {
			domain = CoreServiceLocator.getSystemService().findDomain(new Long(this.getDomainId()));
		}
		return(domain);
	}
	
	/**
     * @return Returns the personId.
     */
    public String getPersonId() {
        return personId;
    }
    
    /**
     * @param personId The personId to set.
     */
    public void setPersonId(String personId) {
        this.personId = personId;
    }

    public boolean getHiddenBoolean() {
    	if (getHidden().toLowerCase().startsWith("tr")) {
    		return true;
    	} else {
    		return false;
    	}
    }
    
	/**
	 * @return Returns the hidden.
	 */
	public String getHidden() {
		return hidden;
	}

	/**
	 * @param hidden The hidden to set.
	 */
	public void setHidden(String hidden) {
		this.hidden = hidden;
	}
}

